package Model;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.Timer;

import Config.Constantes;
import Dificultad.Dificultad;
import View.*;
import mvc.Model;
public class ArenaModel implements ActionListener, ISubject, Model {
	
	ArrayList<NaveModelInterface> enemigos = new ArrayList<NaveModelInterface>();
	NaveAliada aliado;
	ArrayList<Observer> vistas = new ArrayList<Observer>();
	ArrayList<Misil> ms = new ArrayList<Misil>();
	Timer timer;
	EstadoContextGame estadoGame;
	public ArenaModel(Dificultad dificultad)
	{	
		AbstractNaveFactory factoryAlienA = new FactoryAlienA();
		AbstractNaveFactory factoryAlienB = new FactoryAlienB();
		
		aliado = new NaveAliada(20,60);
		timer = new Timer(10, this);
		
		timer.start();
		for(int i = 0; i < dificultad.getNaves()/2; i++)
		{
			int aux = aleatorio();
			//Random rn = new Random();

			enemigos.add(factoryAlienA.crear(200 * (i + 1), aux + 2));

			enemigos.add(factoryAlienB.crear(200 * (i + 1), aux + 2));
		}
		ms = aliado.getMissiles();
		
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		

		// ---  para actualizar posicion naves
		moverAliens();
		comprobarEstadoAliado();
		this.notifyObservers();
		//repaint(); // repaint llama a paint()

	}
	public void moverAliens()
	{
		NaveModelInterface alien; 			
		System.out.println(aliado.getEscudoAsString());
	
		for(int i = 0; i < enemigos.size(); i ++)
		{
				
			if (enemigos.get(i).isVisible()) {
				
				alien = (NaveModelInterface) enemigos.get(i);
				comprobarMisilesDisparados(alien);
				aliado.getComportamiento().comprobar();
				
				if (alien.collision(aliado)) {
					aliado.getComportamiento().ejecutar(alien);
					
				}
			
				aliado.posicionar();
				alien.posicionar();
				// actualizamos posicion de cada enemigo en el array de enemigos	
				enemigos.set(i, alien);
				
			} else {
				enemigos.remove(i);

			}
			moverMisiles();
		}

		
	}
	
	private void comprobarMisilesDisparados(NaveModelInterface alien){
		for (int j = 0; j < ms.size(); j++) {
			Misil m = (Misil) ms.get(j);

			if (alien.collision(m)) {
				m.visible = false;
				ms.remove(j);
				alien.visible = false;
				aliado.addPuntos();
			}

		}
		
	}
	// cuando pierde vida, reiniciamos posiciones
	public void reinciarPosicionAliado(){
		aliado.setX(20);
		aliado.setY(20);
		aliado.visible = true;
	}
	// cuando pierde vida, reiniciamos posiciones
	public void reiniciarPosicionAliens(){
		NaveModelInterface alien; 
		for(int i = 0; i < enemigos.size(); i ++){
			if (enemigos.get(i).isVisible()) {
				alien = (NaveModelInterface) enemigos.get(i);
				alien.setX(200 * (i + 1));
				alien.setY(aleatorio()+2);
				enemigos.set(i, alien);
			}
			else{
				enemigos.remove(i);
			}
		}
	}
	public ArrayList<Misil> getMisilesActualizados(){
		return ms;
	}
	private void moverMisiles(){
		//System.out.println(ms);
		for (int i = 0; i < ms.size(); i++) {
            Misil m = (Misil) ms.get(i);
            if (m.isVisible()) 
                m.move();
            else ms.remove(i);
        }
	}
	
	public ArenaModel(ArrayList<NaveModelInterface> enemigos, NaveAliada aliado){
		this.enemigos = enemigos;
		this.aliado = aliado;
	}
	
	private int aleatorio()	{
		return (int)(Math.random()*20+1);
	}
	
	public ArrayList<NaveModelInterface> getEnemigos() {
		return enemigos;
	}

	public void setEnemigos(ArrayList<NaveModelInterface> enemigos) {
		this.enemigos = enemigos;
	}

	public NaveAliada getAliado() {
		return aliado;
	}

	public void setAliado(NaveAliada aliado) {
		this.aliado = aliado;
	}
	// observers
	public void registerObserver(Observer v) {
		vistas.add(v);

	}

	public void removeObserver(Observer v) {
		int i = vistas.indexOf(v);
		if (i > 0)
			vistas.remove(i);

	}
	public void notifyObservers(){
		for(Observer observer: vistas){
			observer.updateObserver();
		}
		
	}
	public void comprobarEstadoAliado(){
		
		if(aliado.visible == false){
			//vista.timer.stop();
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			// si pierde
			if(aliado.getVidas()==2)
			{	
				//vista.gameOver();
				
				//setEstado(new EstadoGameOver(this));
				//estado.execute();
			}
			else{
				reiniciarPosicionAliens();
				reinciarPosicionAliado();
				timer.start();
			}
		}
		else if(enemigos.size()==0){
			timer.stop();
			//setEstado(new EstadoGana(this));
			//estado.execute();
			
		}
	}
	
	public String toString(){
		return "pos 0 "+enemigos.get(0).getX() + "pos 1 "+enemigos.get(1).getX();
	}
	public void setKeyPressed(KeyEvent e){
		int key = e.getKeyCode();

        if (key == KeyEvent.VK_LEFT) {
        	if(aliado.getX()  < 0){
        		
        		aliado.setDx(0);
        	}
        	else
        		aliado.setDx(-1);
        }

        if (key == KeyEvent.VK_RIGHT) {
        	if(aliado.getX() + (aliado.getBoundx()) > Constantes.WIDTH)
        		aliado.setDx(0);
        	else
        		aliado.setDx(1);
        }

        if (key == KeyEvent.VK_UP) {
        	if(aliado.getY() + (aliado.getBoundy()) < 0)
        		aliado.setDy(0);
        	else
        		aliado.setDy(-1);
        }

        if (key == KeyEvent.VK_DOWN) {
        	if((aliado.getY() +150)  > Constantes.HEIGHT)
        		aliado.setDy(0);
        	else
        		aliado.setDy(1);
        	
        }
        if (key == KeyEvent.VK_SPACE) {
        	aliado.fire();
        }
	}
	public void setKeyReleased(KeyEvent e){
		int key = e.getKeyCode();

        if (key == KeyEvent.VK_LEFT) {
            aliado.setDx(0);
        }

        if (key == KeyEvent.VK_RIGHT) {
        	aliado.setDx(0);
        }

        if (key == KeyEvent.VK_UP) {
        	aliado.setDy(0);
        }

        if (key == KeyEvent.VK_DOWN) {
        	aliado.setDy(0);
        }
	}
	@Override
	public Model getModel() {
		
		return this;
	}
	
}
